﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using turnos.web.Models;
using turnos.core.modelo;
using turnos.core.util;

namespace turnos.web.Controllers
{
    [HandleError]
    public class WizardController : Controller
    {
        private Solicitantes SolicitanteActual
        {

            get
            {

                if (this.Session["solicitante"] == null)
                    this.Session["solicitante"] = new Solicitantes();
                return (Solicitantes)this.Session["solicitante"];
            }

            set
            {
                this.Session["solicitante"] = value;
            }
        }
        private string TipoDeTramite
        {
            get
            {

                if (this.Session["tipotramite"] == null)
                    this.Session["tipotramite"] = "";
                return this.Session["tipotramite"].ToString();
            }

            set
            {
                this.Session["tipotramite"] = value;
            }
        }


        public WizardModel WizardModel
        {
            get
            {

                if (this.Session["wizardModel"] == null)
                    this.Session["wizardModel"] = new WizardModel();
                return (WizardModel)this.Session["wizardModel"];
            }
        }

        public ActionResult Requisitos()
        {
            ViewData["Message"] = "Requisitos";

            return View();
        }

        public ActionResult TipoTramite()
        {
            ViewData["Message"] = "Tipo de trámite a realizar";

            ViewData["idTipoTramite"] = new SelectList(this.WizardModel.TiposTramites, "IdTipoTramite", "TipoTramite1");

            return View();
        }

        public ActionResult DatosSolicitante(string tipoTramite)
        {

            ViewData["Message"] = "Datos del solicitante";
            SolicitanteActual = null;
            ViewData["idTipoDocumento"] = new SelectList(this.WizardModel.TiposDocumentos, "IdTipoDocumento", "TipoDocumento");
            ViewData["idSexo"] = new SelectList(this.WizardModel.Sexos, "IdSexo", "NombreSexo");

            return View();
        }

        public ActionResult Confirmacion()
        {

            ViewData["Message"] = "Confirmación del turno";
            ViewData["idFecha"] = new SelectList(this.WizardModel.Fechas, "fecha", "fecha");
            List<AgendaDeTurnos> a = new List<AgendaDeTurnos>();
            ViewData["idHora"] = new SelectList(new List<AgendaDeTurnos>());
            if (this.WizardModel.Fechas.Count > 0)
            {
                List<AgendaDeTurnos> ags = this.WizardModel.TurnosC.TraerAgendaPorFecha(DateTime.Parse(this.WizardModel.Fechas[0].fecha), 1, null);

                ViewData["idHora"] = new SelectList((from t in ags
                                                     where (Convert.ToDateTime(t.Fecha) > DateTime.Now.AddDays(-1) && Convert.ToDateTime(t.Fecha) < DateTime.Now.AddDays(60))

                                                     select new { id = t.FechayHora.ToShortTimeString(), nombre = t.FechayHora.ToShortTimeString() }).Distinct(), "id", "nombre");
            }
            return View();
        }

        public ActionResult Confirmar(string fecha, string hora)
        {
            Resultado resultado = new Resultado { ok = true, msg = "Se confirmó el turno", url = "Confirmación", tipoTramite = this.TipoDeTramite };
            int doc;
            try
            {
                if (SolicitanteActual == null)
                    throw new Exception("La sesión caducó, debera realizar nuevamente el trámite.");

                if ((fecha == null) || (fecha == String.Empty))
                    throw new Exception("No seleccionó una fecha válida.");

                if ((hora == null) || (hora == String.Empty))
                    throw new Exception("No seleccionó una hora válida.");

                var turnos = this.WizardModel.TurnosC.TraerAgendaPorFecha(DateTime.Parse(fecha), 1, null);

                var turno = (from t in turnos
                             where t.FechayHora.ToShortTimeString() == hora
                             select t).ToList();

                SolicitanteUI sol = SuperaCantidadDeSolicitudesEnLaSemana(SolicitanteActual, fecha);
                if (sol != null)
                {
                    resultado.solicitante = sol;
                    throw new turnosException("Ud. ha superado la cantidad permitida de solicitudes de turnos. Reeimprima su turno.");
                }

                if (this.TipoDeTramite == "2" || this.TipoDeTramite == "3")

                    if ((!SolicitanteActual.FechaProxVenc.HasValue) || (SolicitanteActual.FechaProxVenc.Value.ToShortDateString() == "01/01/0001"))
                        throw new Exception(turnosCts.Format(turnosCts.SOLICITANTE_DATO_INVALIDO, " Fecha de Vencimiento "));


                if (turno.Count > 0)
                {
                    SolicitanteUI sol_ui = this.crearSolicitanteUI(SolicitanteActual);
                    sol_ui.Fecha = fecha;
                    sol_ui.Hora = hora;
                    sol_ui.TipoTramite = this.WizardModel.TurnosC.TraerTiposTramites(byte.Parse(this.TipoDeTramite)).SingleOrDefault().TipoTramite1;
                    resultado.solicitante = sol_ui;
                    turno[0].RefTipoTramite = this.WizardModel.TurnosC.TraerTiposTramites(byte.Parse(this.TipoDeTramite)).SingleOrDefault().IdTipoTramite;
                    this.WizardModel.TurnosC.GuardarSolicitante(this.SolicitanteActual, turno[0], "usuarioWEB", true);
                }
                else
                    throw new Exception("No se pudo confirmar el turno, posiblemente otro usuario tomo en forma simultanea dicho horario. Por favor seleccione otro horario u otro día.");

            }

            catch (turnosException ex)
            {
                resultado.msg = ex.Message;
            }

            catch (Exception ex)
            {
                resultado.ok = false;
                resultado.msg = ex.Message;
            }

            return Json(resultado);
        }

        private SolicitanteUI SuperaCantidadDeSolicitudesEnLaSemana(Solicitantes SolicitanteActual, string fecha)
        {
            SolicitanteUI sol_ui = null;

            List<AgendaDeTurnos> lista = this.WizardModel.TurnosC.TraerSolicitudesDelSolicitante(SolicitanteActual.RefTipoDocumento, SolicitanteActual.NroDocumento, SolicitanteActual.Sexo);
            DateTime hoy = DateTime.Now;
            DateTime semana = DateTime.Now.AddDays(-7);
            List<AgendaDeTurnos> lis = (from a in lista
                                        where Convert.ToDateTime(a.Fecha) <= hoy && Convert.ToDateTime(a.Fecha) >= semana
                                        select a).ToList();

            if (lis.Count >= 1)
            {
                sol_ui = crearSolicitanteUI(SolicitanteActual);
                sol_ui.Fecha = lis[0].Fecha;
                sol_ui.Hora = lis[0].FechayHora.ToShortTimeString();
                sol_ui.TipoTramite = this.WizardModel.TurnosC.TraerTiposTramites(byte.Parse(lis[0].RefTipoTramite.Value.ToString())).SingleOrDefault().TipoTramite1;
                this.TipoDeTramite = lis[0].RefTipoTramite.Value.ToString();
            }
            return sol_ui;
        }

        public ActionResult CargarHoras(DateTime fecha)
        {
            List<AgendaDeTurnos> ags = this.WizardModel.TurnosC.TraerAgendaPorFecha(fecha, 1, null);
            return Json((from t in ags select new { id = t.FechayHora.ToShortTimeString(), nombre = t.FechayHora.ToShortTimeString() }).Distinct());
        }

        public ActionResult SeleccionarTipoTramite(string idTipoTramite)
        {
            TipoDeTramite = idTipoTramite;

            Resultado resultado = new Resultado { ok = true, msg = "Se selecciono exitosamente", url = "./DatosSolicitante?tipoTramite=" + TipoDeTramite };
            return Json(resultado);
        }

        public ActionResult BuscarSolicitante(string idTipoDocumento, string nroDocumento, int sexo)
        {
            Resultado resultado = new Resultado { ok = true, msg = "Se busco exitosamente" };
            int doc;
            try
            {
                int.TryParse(nroDocumento, out doc);
                if (doc == 0)
                    throw new Exception("Debe indicar un número de documento correcto");

                SolicitanteActual = WizardModel.TurnosC.TraerSolicitante(idTipoDocumento, nroDocumento, sexo);
                SolicitanteActual.RefTipoDocumento = byte.Parse(idTipoDocumento);
                SolicitanteActual.NroDocumento = doc;

                SolicitanteActual.Sexo = (sexo == 0 ? "M" : "F");

                resultado.solicitante = crearSolicitanteUI(SolicitanteActual);
            }
            catch (Exception ex)
            {
                resultado.ok = false;
                resultado.msg = ex.Message;
            }

            return Json(resultado);
        }

        private SolicitanteUI crearSolicitanteUI(Solicitantes sol)
        {
            SolicitanteUI res = new SolicitanteUI();
            res.idSoliciante = sol.IdSolicitante;
            res.RefTipoDocumento = sol.RefTipoDocumento;
            res.TipoDocumento = this.WizardModel.TurnosC.TraerTiposDocumentos(byte.Parse(sol.RefTipoDocumento.ToString())).SingleOrDefault().TipoDocumento;
            res.NroDocumento = sol.NroDocumento;
            res.Sexo = sol.Sexo;
            res.ApeyNom = sol.ApeyNom;
            res.Email = sol.Email;
            res.FechaVto = sol.FechaProxVenc.HasValue ? sol.FechaProxVenc.Value.ToShortDateString() : "";
            res.TipoTramite = this.TipoDeTramite;
            return res;
        }

        public ActionResult GuardarSolicitante(string apynom, string email, string fechavto)
        {
            Resultado resultado = new Resultado { ok = true, msg = "Se busco exitosamente", url = "Confirmacion" };
            int doc;
            DateTime fvto;
            try
            {
                DateTime.TryParse(fechavto, out fvto);
                SolicitanteActual.ApeyNom = apynom;
                SolicitanteActual.Email = email;
                SolicitanteActual.FechaProxVenc = fechavto == string.Empty ? (DateTime?)null : fvto;
                if ((this.TipoDeTramite != "1") && (this.TipoDeTramite != "5"))
                {
                    if (!SolicitanteActual.FechaProxVenc.HasValue)
                        throw new turnosException("La fecha de vencimiento es obligatoria.");
                    else
                    {
                        /*if (SolicitanteActual.FechaProxVenc.Value <= DateTime.Now)
                            throw new turnosException("La fecha de vencimiento debe ser mayor a hoy.");*/
                        if (DateTime.Now.AddDays(30) < SolicitanteActual.FechaProxVenc.Value)
                            throw new turnosException("Ud. puede solicitar un turno hasta 30 días antes de su vencimiento");
                        if (DateTime.Now.AddDays(-90) > SolicitanteActual.FechaProxVenc.Value)
                            throw new turnosException("Su licencia superó los 90 días para poder renovar, debe ingresar el trámite por original");
                    }

                }
            }
            catch (Exception ex)
            {
                resultado.ok = false;
                resultado.msg = ex.Message;
            }

            return Json(resultado);
        }

        public ActionResult Documentacion()
        {

            ViewData["Message"] = "Documentación requerida para cumplimentar el trámite.";

            return View();
        }

        public ActionResult About()
        {
            return View();
        }


        #region Clases anidadas
        private class Resultado
        {
            public bool ok { get; set; }
            public string msg { get; set; }
            public string tipoTramite { get; set; }
            public string url { get; set; }
            public SolicitanteUI solicitante { get; set; }
        }



        private class SolicitanteUI
        {
            public int idSoliciante { get; set; }
            public int RefTipoDocumento { get; set; }
            public string TipoDocumento { get; set; }
            public int NroDocumento { get; set; }
            public string Sexo { get; set; }
            public string ApeyNom { get; set; }
            public string Email { get; set; }
            public string Fecha { get; set; }
            public string Hora { get; set; }
            public string TipoTramite { get; set; }
            public string FechaVto { get; set; }
        }

        #endregion
    }
}

